home *** CD-ROM | disk | FTP | other *** search
/ Chip 2005 June / ccd0605.iso / Software / Freeware / Programare / highlight / highlight-W32GUI-2.2-10b-Setup.exe / {app} / src / ASBeautifier.cpp < prev    next >
C/C++ Source or Header  |  2004-06-29  |  69KB  |  1,979 lines

  1. /*
  2.  * Copyright (c) 1998,1999,2000,2001,2002 Tal Davidson. All rights reserved.
  3.  *
  4.  * ASBeautifier.cpp
  5.  * by Tal Davidson (davidsont@bigfoot.com)
  6.  * This file is a part of "Artistic Style" - an indentater and reformatter
  7.  * of C, C, C# and Java source files.
  8.  *
  9.  * The "Artistic Style" project, including all files needed to compile it,
  10.  * is free software; you can redistribute it and/or use it and/or modify it
  11.  * under the terms of the GNU General Public License as published 
  12.  * by the Free Software Foundation; either version 2 of the License, 
  13.  * or (at your option) any later version.
  14.  *
  15.  * This program is distributed in the hope that it will be useful,
  16.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  18.  *
  19.  * You should have received a copy of the GNU General Public
  20.  * License along with this program.
  21.  *
  22.  * Patches:
  23.  * 18 March 1999 - Brian Rampel -
  24.  *       Fixed inverse insertion of spaces vs. tabs when in -t mode.
  25.  * 08 may 2004 
  26.  *       applied ASBeautifier.cpp.BITFIELD.patch.bz2
  27.  */
  28.  
  29. #include "compiler_defines.h"
  30. #include "ASBeautifier.h"
  31.  
  32. #include <vector>
  33. #include <string>
  34. #include <cctype>
  35. #include <algorithm>
  36. #include <iostream>
  37.  
  38.  
  39. #define INIT_CONTAINER(container, value)     {if ( (container) != NULL ) delete (container); (container) = (value); }
  40. #define DELETE_CONTAINER(container)          {if ( (container) != NULL ) delete (container) ; }
  41.  
  42. #ifdef USES_NAMESPACE
  43. using namespace std;
  44. #endif
  45.  
  46.  
  47.  
  48.  
  49. #ifdef USES_NAMESPACE
  50. namespace astyle
  51.   {
  52. #endif
  53.  
  54.   bool ASBeautifier::calledInitStatic = false;
  55.  
  56.   vector<const string*> ASBeautifier::headers;
  57.   vector<const string*> ASBeautifier::nonParenHeaders;
  58.   vector<const string*> ASBeautifier::preBlockStatements;
  59.   vector<const string*> ASBeautifier::assignmentOperators;
  60.   vector<const string*> ASBeautifier::nonAssignmentOperators;
  61.  
  62.   /*
  63.    * initialize the static vars
  64.    */
  65.   void ASBeautifier::initStatic()
  66.   {
  67.     if (calledInitStatic)
  68.       return;
  69.  
  70.     calledInitStatic = true;
  71.  
  72.     headers.push_back(&AS_IF);
  73.     headers.push_back(&AS_ELSE);
  74.     headers.push_back(&AS_FOR);
  75.     headers.push_back(&AS_WHILE);
  76.     headers.push_back(&AS_DO);
  77.     headers.push_back(&AS_TRY);
  78.     headers.push_back(&AS_CATCH);
  79.     headers.push_back(&AS_FINALLY);
  80.     headers.push_back(&AS_SYNCHRONIZED);
  81.     headers.push_back(&AS_SWITCH);
  82.     headers.push_back(&AS_CASE);
  83.     headers.push_back(&AS_DEFAULT);
  84.     headers.push_back(&AS_FOREACH);
  85.     headers.push_back(&AS_LOCK);
  86.     headers.push_back(&AS_UNSAFE);
  87.     headers.push_back(&AS_FIXED);
  88.     headers.push_back(&AS_GET);
  89.     headers.push_back(&AS_SET);
  90.     headers.push_back(&AS_ADD);
  91.     headers.push_back(&AS_REMOVE);
  92.     //headers.push_back(&AS_PUBLIC);
  93.     //headers.push_back(&AS_PRIVATE);
  94.     //headers.push_back(&AS_PROTECTED);
  95.  
  96.     //headers.push_back(&AS_OPERATOR);
  97.     headers.push_back(&AS_TEMPLATE);
  98.     headers.push_back(&AS_CONST);
  99.     /**/
  100.     headers.push_back(&AS_STATIC);
  101.     headers.push_back(&AS_EXTERN);
  102.  
  103.     nonParenHeaders.push_back(&AS_ELSE);
  104.     nonParenHeaders.push_back(&AS_DO);
  105.     nonParenHeaders.push_back(&AS_TRY);
  106.     nonParenHeaders.push_back(&AS_FINALLY);
  107.     nonParenHeaders.push_back(&AS_STATIC);
  108.     nonParenHeaders.push_back(&AS_CONST);
  109.     nonParenHeaders.push_back(&AS_EXTERN);
  110.     nonParenHeaders.push_back(&AS_CASE);
  111.     nonParenHeaders.push_back(&AS_DEFAULT);
  112.     nonParenHeaders.push_back(&AS_UNSAFE);
  113.     nonParenHeaders.push_back(&AS_GET);
  114.     nonParenHeaders.push_back(&AS_SET);
  115.     nonParenHeaders.push_back(&AS_ADD);
  116.     nonParenHeaders.push_back(&AS_REMOVE);
  117.  
  118.  
  119.  
  120.     nonParenHeaders.push_back(&AS_PUBLIC);
  121.     nonParenHeaders.push_back(&AS_PRIVATE);
  122.     nonParenHeaders.push_back(&AS_PROTECTED);
  123.     nonParenHeaders.push_back(&AS_TEMPLATE);
  124.     nonParenHeaders.push_back(&AS_CONST);
  125.     ///    nonParenHeaders.push_back(&AS_ASM);
  126.  
  127.     preBlockStatements.push_back(&AS_CLASS);
  128.     preBlockStatements.push_back(&AS_STRUCT);
  129.     preBlockStatements.push_back(&AS_UNION);
  130.     preBlockStatements.push_back(&AS_INTERFACE);
  131.     preBlockStatements.push_back(&AS_NAMESPACE);
  132.     preBlockStatements.push_back(&AS_THROWS);
  133.     preBlockStatements.push_back(&AS_EXTERN);
  134.  
  135.     assignmentOperators.push_back(&AS_ASSIGN);
  136.     assignmentOperators.push_back(&AS_PLUS_ASSIGN);
  137.     assignmentOperators.push_back(&AS_MINUS_ASSIGN);
  138.     assignmentOperators.push_back(&AS_MULT_ASSIGN);
  139.     assignmentOperators.push_back(&AS_DIV_ASSIGN);
  140.     assignmentOperators.push_back(&AS_MOD_ASSIGN);
  141.     assignmentOperators.push_back(&AS_OR_ASSIGN);
  142.     assignmentOperators.push_back(&AS_AND_ASSIGN);
  143.     assignmentOperators.push_back(&AS_XOR_ASSIGN);
  144.     assignmentOperators.push_back(&AS_GR_GR_GR_ASSIGN);
  145.     assignmentOperators.push_back(&AS_GR_GR_ASSIGN);
  146.     assignmentOperators.push_back(&AS_LS_LS_LS_ASSIGN);
  147.     assignmentOperators.push_back(&AS_LS_LS_ASSIGN);
  148.  
  149.     assignmentOperators.push_back(&AS_RETURN);
  150.  
  151.     nonAssignmentOperators.push_back(&AS_EQUAL);
  152.     nonAssignmentOperators.push_back(&AS_PLUS_PLUS);
  153.     nonAssignmentOperators.push_back(&AS_MINUS_MINUS);
  154.     nonAssignmentOperators.push_back(&AS_NOT_EQUAL);
  155.     nonAssignmentOperators.push_back(&AS_GR_EQUAL);
  156.     nonAssignmentOperators.push_back(&AS_GR_GR_GR);
  157.     nonAssignmentOperators.push_back(&AS_GR_GR);
  158.     nonAssignmentOperators.push_back(&AS_LS_EQUAL);
  159.     nonAssignmentOperators.push_back(&AS_LS_LS_LS);
  160.     nonAssignmentOperators.push_back(&AS_LS_LS);
  161.     nonAssignmentOperators.push_back(&AS_ARROW);
  162.     nonAssignmentOperators.push_back(&AS_AND);
  163.     nonAssignmentOperators.push_back(&AS_OR);
  164.   }
  165.  
  166.   /**
  167.    * ASBeautifier's constructor
  168.    */
  169.   ASBeautifier::ASBeautifier()
  170.   {
  171.     initStatic();
  172.  
  173.     waitingBeautifierStack = NULL;
  174.     activeBeautifierStack = NULL;
  175.     waitingBeautifierStackLengthStack = NULL;
  176.     activeBeautifierStackLengthStack = NULL;
  177.  
  178.     headerStack  = NULL;
  179.     tempStacks = NULL;
  180.     blockParenDepthStack = NULL;
  181.     blockStatementStack = NULL;
  182.     parenStatementStack = NULL;
  183.     bracketBlockStateStack = NULL;
  184.     inStatementIndentStack = NULL;
  185.     inStatementIndentStackSizeStack = NULL;
  186.     parenIndentStack = NULL;
  187.     sourceIterator = NULL;
  188.  
  189.     isMinimalConditinalIndentSet = false;
  190.     shouldForceTabIndentation = false;
  191.  
  192.     setSpaceIndentation(4);
  193.     setMaxInStatementIndentLength(40);
  194.     setClassIndent(false);
  195.     setSwitchIndent(false);
  196.     setCaseIndent(false);
  197.     setBlockIndent(false);
  198.     setBracketIndent(false);
  199.     setNamespaceIndent(false);
  200.     setLabelIndent(false);
  201.     setEmptyLineFill(false);
  202.     setCStyle();
  203.     setPreprocessorIndent(false);
  204.   }
  205.  
  206.   ASBeautifier::ASBeautifier(const ASBeautifier &other)
  207.   {
  208.     waitingBeautifierStack = NULL;
  209.     activeBeautifierStack = NULL;
  210.     waitingBeautifierStackLengthStack = NULL;
  211.     activeBeautifierStackLengthStack = NULL;
  212.  
  213.     headerStack  = new vector<const string*>;
  214.     *headerStack = *other.headerStack;
  215.  
  216.     tempStacks = new vector< vector<const string*>* >;
  217.     vector< vector<const string*>* >::iterator iter;
  218.     for (iter = other.tempStacks->begin();
  219.          iter != other.tempStacks->end();
  220.          ++iter)
  221.       {
  222.         vector<const string*> *newVec = new vector<const string*>;
  223.         *newVec = **iter;
  224.         tempStacks->push_back(newVec);
  225.       }
  226.     blockParenDepthStack = new vector<int>;
  227.     *blockParenDepthStack = *other.blockParenDepthStack;
  228.  
  229.     blockStatementStack = new vector<bool>;
  230.     *blockStatementStack = *other.blockStatementStack;
  231.  
  232.     parenStatementStack =  new vector<bool>;
  233.     *parenStatementStack = *other.parenStatementStack;
  234.  
  235.     bracketBlockStateStack = new vector<bool>;
  236.     *bracketBlockStateStack = *other.bracketBlockStateStack;
  237.  
  238.     inStatementIndentStack = new vector<int>;
  239.     *inStatementIndentStack = *other.inStatementIndentStack;
  240.  
  241.     inStatementIndentStackSizeStack = new vector<int>;
  242.     *inStatementIndentStackSizeStack = *other.inStatementIndentStackSizeStack;
  243.  
  244.     parenIndentStack = new vector<int>;
  245.     *parenIndentStack = *other.parenIndentStack;
  246.  
  247.     sourceIterator = other.sourceIterator;
  248.  
  249.     indentString = other.indentString;
  250.     currentHeader = other.currentHeader;
  251.     previousLastLineHeader = other.previousLastLineHeader;
  252.     immediatelyPreviousAssignmentOp = other.immediatelyPreviousAssignmentOp;
  253.     isInQuote = other.isInQuote;
  254.     isInComment = other.isInComment;
  255.     isInCase = other.isInCase;
  256.     isInQuestion = other.isInQuestion;
  257.     isInStatement =other. isInStatement;
  258.     isInHeader = other.isInHeader;
  259.     isCStyle = other.isCStyle;
  260.     isInOperator = other.isInOperator;
  261.     isInTemplate = other.isInTemplate;
  262.     isInConst = other.isInConst;
  263.     classIndent = other.classIndent;
  264.     isInClassHeader = other.isInClassHeader;
  265.     isInClassHeaderTab = other.isInClassHeaderTab;
  266.     switchIndent = other.switchIndent;
  267.     caseIndent = other.caseIndent;
  268.     namespaceIndent = other.namespaceIndent;
  269.     bracketIndent = other.bracketIndent;
  270.     blockIndent = other.blockIndent;
  271.     labelIndent = other.labelIndent;
  272.     preprocessorIndent = other.preprocessorIndent;
  273.     parenDepth = other.parenDepth;
  274.     indentLength = other.indentLength;
  275.     blockTabCount = other.blockTabCount;
  276.     leadingWhiteSpaces = other.leadingWhiteSpaces;
  277.     maxInStatementIndent = other.maxInStatementIndent;
  278.     templateDepth = other.templateDepth;
  279.     quoteChar = other.quoteChar;
  280.     prevNonSpaceCh = other.prevNonSpaceCh;
  281.     currentNonSpaceCh = other.currentNonSpaceCh;
  282.     currentNonLegalCh = other.currentNonLegalCh;
  283.     prevNonLegalCh = other.prevNonLegalCh;
  284.     isInConditional = other.isInConditional;
  285.     minConditionalIndent = other.minConditionalIndent;
  286.     prevFinalLineSpaceTabCount = other.prevFinalLineSpaceTabCount;
  287.     prevFinalLineTabCount = other.prevFinalLineTabCount;
  288.     emptyLineFill = other.emptyLineFill;
  289.     probationHeader = other.probationHeader;
  290.     isInDefine = other.isInDefine;
  291.     isInDefineDefinition = other.isInDefineDefinition;
  292.     backslashEndsPrevLine = other.backslashEndsPrevLine;
  293.     defineTabCount = other.defineTabCount;
  294.   }
  295.  
  296.   /**
  297.    * ASBeautifier's destructor
  298.    */
  299.   ASBeautifier::~ASBeautifier()
  300.   {
  301.     DELETE_CONTAINER( headerStack );
  302.     DELETE_CONTAINER( tempStacks );
  303.     DELETE_CONTAINER( blockParenDepthStack );
  304.     DELETE_CONTAINER( blockStatementStack );
  305.     DELETE_CONTAINER( parenStatementStack );
  306.     DELETE_CONTAINER( bracketBlockStateStack );
  307.     DELETE_CONTAINER( inStatementIndentStack );
  308.     DELETE_CONTAINER( inStatementIndentStackSizeStack );
  309.     DELETE_CONTAINER( parenIndentStack );
  310.  
  311.     // DELETE_CONTAINER( sourceIterator );
  312.   }
  313.  
  314.   /**
  315.    * initialize the ASBeautifier.
  316.    *
  317.    * init() should be called every time a ABeautifier object is to start
  318.    * beautifying a NEW source file.
  319.    * init() recieves a pointer to a DYNAMICALLY CREATED ASSourceIterator object
  320.    * that will be used to iterate through the source code. This object will be
  321.    * deleted during the ASBeautifier's destruction, and thus should not be
  322.    * deleted elsewhere.
  323.    *
  324.    * @param iter     a pointer to the DYNAMICALLY CREATED ASSourceIterator object.
  325.    */
  326.   void ASBeautifier::init(ASSourceIterator *iter)
  327.  
  328.   {
  329.     sourceIterator = iter;
  330.     init();
  331.   }
  332.  
  333.   /**
  334.    * initialize the ASBeautifier.
  335.    */
  336.   void ASBeautifier::init()
  337.   {
  338.     INIT_CONTAINER( waitingBeautifierStack,  new vector<ASBeautifier*> );
  339.     INIT_CONTAINER( activeBeautifierStack,  new vector<ASBeautifier*> );
  340.  
  341.     INIT_CONTAINER( waitingBeautifierStackLengthStack, new vector<int> );
  342.     INIT_CONTAINER( activeBeautifierStackLengthStack, new vector<int> );
  343.  
  344.     INIT_CONTAINER( headerStack,  new vector<const string*> );
  345.     INIT_CONTAINER( tempStacks, new vector< vector<const string*>* > );
  346.     tempStacks->push_back(new vector<const string*>);
  347.  
  348.     INIT_CONTAINER( blockParenDepthStack, new vector<int> );
  349.     INIT_CONTAINER( blockStatementStack, new vector<bool> );
  350.     INIT_CONTAINER( parenStatementStack, new vector<bool> );
  351.  
  352.     INIT_CONTAINER( bracketBlockStateStack, new vector<bool> );
  353.     bracketBlockStateStack->push_back(true);
  354.  
  355.     INIT_CONTAINER( inStatementIndentStack, new vector<int> );
  356.     INIT_CONTAINER( inStatementIndentStackSizeStack, new vector<int> );
  357.     inStatementIndentStackSizeStack->push_back(0);
  358.     INIT_CONTAINER( parenIndentStack, new vector<int> );
  359.  
  360.     immediatelyPreviousAssignmentOp = NULL;
  361.     previousLastLineHeader = NULL;
  362.  
  363.     isInQuote = false;
  364.     isInComment = false;
  365.     isInStatement = false;
  366.     isInCase = false;
  367.     isInQuestion = false;
  368.     isInClassHeader = false;
  369.     isInClassHeaderTab = false;
  370.     isInHeader = false;
  371.     isInOperator = false;
  372.     isInTemplate = false;
  373.     isInConst = false;
  374.     isInConditional = false;
  375.     templateDepth = 0;
  376.     parenDepth=0;
  377.     blockTabCount = 0;
  378.     leadingWhiteSpaces = 0;
  379.     prevNonSpaceCh = '{';
  380.     currentNonSpaceCh = '{';
  381.     prevNonLegalCh = '{';
  382.     currentNonLegalCh = '{';
  383.     prevFinalLineSpaceTabCount = 0;
  384.     prevFinalLineTabCount = 0;
  385.     probationHeader = NULL;
  386.     backslashEndsPrevLine = false;
  387.     isInDefine = false;
  388.     isInDefineDefinition = false;
  389.     defineTabCount = 0;
  390.   }
  391.  
  392.   /**
  393.    * set indentation style to ANSI C/C++.  
  394.    */
  395.   void ASBeautifier::setCStyle()
  396.   {
  397.     isCStyle = true;
  398.   }
  399.  
  400.   /**
  401.    * set indentation style to Java / K&R.  
  402.    */
  403.   void ASBeautifier::setJavaStyle()
  404.   {
  405.     isCStyle = false;
  406.   }
  407.  
  408.   /**
  409.    * indent using one tab per indentation
  410.    */
  411.   void ASBeautifier::setTabIndentation(int length, bool forceTabs)
  412.   {
  413.     indentString = "\t";
  414.     indentLength = length;
  415.     shouldForceTabIndentation = forceTabs;
  416.  
  417.     if (!isMinimalConditinalIndentSet)
  418.       minConditionalIndent = indentLength * 2;
  419.   }
  420.  
  421.   /**
  422.    
  423.    * indent using a number of spaces per indentation.
  424.    *
  425.    * @param   length     number of spaces per indent.
  426.    */
  427.   void ASBeautifier::setSpaceIndentation(int length)
  428.   {
  429.     indentString=string(length, ' ');
  430.     indentLength = length;
  431.  
  432.     if (!isMinimalConditinalIndentSet)
  433.       minConditionalIndent = indentLength * 2;
  434.   }
  435.  
  436.   /**
  437.    * set the maximum indentation between two lines in a multi-line statement.
  438.    *
  439.    * @param   max     maximum indentation length.
  440.    */
  441.   void ASBeautifier::setMaxInStatementIndentLength(int max)
  442.   {
  443.     maxInStatementIndent = max;
  444.   }
  445.  
  446.   /**
  447.    * set the minimum indentation between two lines in a multi-line condition.
  448.    *
  449.    * @param   min     minimal indentation length.
  450.    */
  451.   void ASBeautifier::setMinConditionalIndentLength(int min)
  452.   {
  453.     minConditionalIndent = min;
  454.     isMinimalConditinalIndentSet = true;
  455.   }
  456.  
  457.   /**
  458.    * set the state of the bracket indentation option. If true, brackets will 
  459.    * be indented one additional indent.
  460.    *
  461.    * @param   state             state of option.
  462.    */
  463.   void ASBeautifier::setBracketIndent(bool state)
  464.   {
  465.     bracketIndent = state;
  466.   }
  467.  
  468.   /**
  469.    * set the state of the block indentation option. If true, entire blocks 
  470.    * will be indented one additional indent, similar to the GNU indent style.
  471.    *
  472.    * @param   state             state of option.
  473.    */
  474.   void ASBeautifier::setBlockIndent(bool state)
  475.   {
  476.     if (state)
  477.       setBracketIndent(false); // so that we don't have both bracket and block indent
  478.     blockIndent = state;
  479.   }
  480.  
  481.   /**
  482.    * set the state of the class indentation option. If true, C++ class
  483.    * definitions will be indented one additional indent.
  484.    *
  485.    * @param   state             state of option.
  486.    */
  487.   void ASBeautifier::setClassIndent(bool state)
  488.   {
  489.     classIndent = state;
  490.   }
  491.  
  492.   /**
  493.    * set the state of the switch indentation option. If true, blocks of 'switch' 
  494.    * statements will be indented one additional indent.
  495.    *
  496.    * @param   state             state of option.
  497.    */
  498.   void ASBeautifier::setSwitchIndent(bool state)
  499.   {
  500.     switchIndent = state;
  501.   }
  502.  
  503.   /**
  504.    * set the state of the case indentation option. If true, lines of 'case' 
  505.    * statements will be indented one additional indent.
  506.    *
  507.    * @param   state             state of option.
  508.    */
  509.   void ASBeautifier::setCaseIndent(bool state)
  510.   {
  511.     caseIndent = state;
  512.   }
  513.   /**
  514.    * set the state of the namespace indentation option. 
  515.    * If true, blocks of 'namespace' statements will be indented one 
  516.    * additional indent. Otherwise, NO indentation will be added.
  517.    *
  518.    * @param   state             state of option.
  519.    */
  520.   void ASBeautifier::setNamespaceIndent(bool state)
  521.   {
  522.     namespaceIndent = state;
  523.   }
  524.  
  525.   /**
  526.    * set the state of the label indentation option. 
  527.    * If true, labels will be indented one indent LESS than the
  528.    * current indentation level.
  529.    * If false, labels will be flushed to the left with NO
  530.    * indent at all.
  531.    *
  532.    * @param   state             state of option.
  533.    */
  534.   void ASBeautifier::setLabelIndent(bool state)
  535.   {
  536.     labelIndent = state;
  537.   }
  538.  
  539.   /**
  540.    * set the state of the preprocessor indentation option. 
  541.    * If true, multiline #define statements will be indented.
  542.    *
  543.    * @param   state             state of option.
  544.    */
  545.   void ASBeautifier::setPreprocessorIndent(bool state)
  546.   {
  547.     preprocessorIndent = state;
  548.   }
  549.  
  550.   /**
  551.    * set the state of the empty line fill option. 
  552.    * If true, empty lines will be filled with the whitespace.
  553.    * of their previous lines.
  554.    * If false, these lines will remain empty.
  555.    *
  556.    * @param   state             state of option.
  557.    */
  558.   void ASBeautifier::setEmptyLineFill(bool state)
  559.   {
  560.     emptyLineFill = state;
  561.   }
  562.  
  563.   /**
  564.    * check if there are any indented lines ready to be read by nextLine()
  565.    *
  566.    * @return    are there any indented lines ready?
  567.    */
  568.   bool ASBeautifier::hasMoreLines() const
  569.     {
  570.       return sourceIterator->hasMoreLines();
  571.     }
  572.  
  573.   /**
  574.    * get the next indented line.
  575.    *
  576.    * @return    indented line.
  577.    */
  578.   string ASBeautifier::nextLine()
  579.   {
  580.     return beautify(sourceIterator->nextLine());
  581.   }
  582.  
  583.   /**
  584.    * beautify a line of source code.
  585.    * every line of source code in a source code file should be sent
  586.    * one after the other to the beautify method.
  587.    *
  588.    * @return      the indented line.
  589.    * @param originalLine       the original unindented line.
  590.    */
  591.   string ASBeautifier::beautify(const string &originalLine)
  592.   {
  593.     string line;
  594.     bool isInLineComment = false;
  595.     bool lineStartsInComment = false;
  596.     bool isInClass = false;
  597.     bool isInSwitch = false;
  598.     bool isImmediatelyAfterConst = false;
  599.     bool isSpecialChar = false;
  600.  
  601.     char ch = ' ';
  602.     char prevCh;
  603.     string outBuffer; // the newly idented line is bufferd here
  604.     int tabCount = 0;
  605.     const string *lastLineHeader = NULL;
  606.     bool closingBracketReached = false;
  607.     int spaceTabCount = 0;
  608.     char tempCh;
  609.     unsigned int headerStackSize = headerStack->size();
  610.     //bool isLineInStatement = isInStatement;
  611.     bool shouldIndentBrackettedLine = true;
  612.     int lineOpeningBlocksNum = 0;
  613.     int lineClosingBlocksNum = 0;
  614.     bool previousLineProbation = (probationHeader != NULL);
  615.     unsigned int i;
  616.  
  617.     currentHeader = NULL;
  618.  
  619.     lineStartsInComment = isInComment;
  620.  
  621.     // handle and remove white spaces around the line:
  622.     // If not in comment, first find out size of white space before line,
  623.     // so that possible comments starting in the line continue in
  624.     // relation to the preliminary white-space.
  625.     if (!isInComment)
  626.       {
  627.         leadingWhiteSpaces = 0;
  628.         while (leadingWhiteSpaces<originalLine.length() && originalLine[leadingWhiteSpaces] <= 0x20)
  629.           leadingWhiteSpaces++;
  630.  
  631.         line = trim(originalLine);
  632.       }
  633.     else
  634.       {
  635.         unsigned int trimSize;
  636.         for (trimSize=0;
  637.              trimSize < originalLine.length() && trimSize<leadingWhiteSpaces && originalLine[trimSize] <= 0x20 ;
  638.              trimSize++)
  639.           ;
  640.         line = originalLine.substr(trimSize);
  641.       }
  642.  
  643.  
  644.     if (line.length() == 0)
  645.       {
  646.         if (emptyLineFill)
  647.           return preLineWS(prevFinalLineSpaceTabCount, prevFinalLineTabCount);
  648.         else
  649.           return line;
  650.       }
  651.  
  652.     // handle preprocessor commands
  653.  
  654.     if (isCStyle && !isInComment && (line[0] == '#' || backslashEndsPrevLine))
  655.       {
  656.         if (line[0] == '#')
  657.           {
  658.             string preproc = trim(string(line.c_str() + 1));
  659.  
  660.  
  661.             // When finding a multi-lined #define statement, the original beautifier
  662.             // 1. sets its isInDefineDefinition flag
  663.             // 2. clones a new beautifier that will be used for the actual indentation
  664.             //    of the #define. This clone is put into the activeBeautifierStack in order
  665.             //    to be called for the actual indentation.
  666.             // The original beautifier will have isInDefineDefinition = true, isInDefine = false
  667.             // The cloned beautifier will have   isInDefineDefinition = true, isInDefine = true
  668.             if (preprocessorIndent && preproc.COMPARE(0, 6, string("define")) == 0 &&  line[line.length() - 1] == '\\')
  669.               {
  670.                 if (!isInDefineDefinition)
  671.                   {
  672.                     ASBeautifier *defineBeautifier;
  673.  
  674.                     // this is the original beautifier
  675.                     isInDefineDefinition = true;
  676.  
  677.                     // push a new beautifier into the active stack
  678.                     // this breautifier will be used for the indentation of this define
  679.                     defineBeautifier = new ASBeautifier(*this);
  680.                     //defineBeautifier->init();
  681.                     //defineBeautifier->isInDefineDefinition = true;
  682.                     //defineBeautifier->beautify("");
  683.                     activeBeautifierStack->push_back(defineBeautifier);
  684.                   }
  685.                 else
  686.                   {
  687.                     // the is the cloned beautifier that is in charge of indenting the #define.
  688.                     isInDefine = true;
  689.                   }
  690.               }
  691.             else if (preproc.COMPARE(0, 2, string("if")) == 0)
  692.               {
  693.                 // push a new beautifier into the stack
  694.                 waitingBeautifierStackLengthStack->push_back(waitingBeautifierStack->size());
  695.                 activeBeautifierStackLengthStack->push_back(activeBeautifierStack->size());
  696.                 waitingBeautifierStack->push_back(new ASBeautifier(*this));
  697.               }
  698.             else if (preproc.COMPARE(0, 4/*2*/, string("else")) == 0)
  699.               {
  700.                 if (!waitingBeautifierStack->empty())
  701.                   {
  702.                     // MOVE current waiting beautifier to active stack.
  703.                     activeBeautifierStack->push_back(waitingBeautifierStack->back());
  704.                     waitingBeautifierStack->pop_back();
  705.                   }
  706.               }
  707.             else if (preproc.COMPARE(0, 4, string("elif")) == 0)
  708.               {
  709.                 if (!waitingBeautifierStack->empty())
  710.                   {
  711.                     // append a COPY current waiting beautifier to active stack, WITHOUT deleting the original.
  712.                     activeBeautifierStack->push_back( new ASBeautifier( *(waitingBeautifierStack->back()) ) );
  713.                   }
  714.               }
  715.             else if (preproc.COMPARE(0, 5, string("endif")) == 0)
  716.               {
  717.                 unsigned int stackLength;
  718.                 ASBeautifier *beautifier;
  719.  
  720.                 if (!waitingBeautifierStackLengthStack->empty())
  721.                   {
  722.                     stackLength = waitingBeautifierStackLengthStack->back();
  723.                     waitingBeautifierStackLengthStack->pop_back();
  724.                     while (waitingBeautifierStack->size() > stackLength)
  725.                       {
  726.                         beautifier = waitingBeautifierStack->back();
  727.                         waitingBeautifierStack->pop_back();
  728.                         delete beautifier;
  729.                       }
  730.                   }
  731.  
  732.                 if (!activeBeautifierStackLengthStack->empty())
  733.                   {
  734.                     stackLength = activeBeautifierStackLengthStack->back();
  735.                     activeBeautifierStackLengthStack->pop_back();
  736.                     while (activeBeautifierStack->size() > stackLength)
  737.                       {
  738.                         beautifier = activeBeautifierStack->back();
  739.                         activeBeautifierStack->pop_back();
  740.                         delete beautifier;
  741.                       }
  742.                   }
  743.  
  744.  
  745.               }
  746.           }
  747.  
  748.         // check if the last char is a backslash
  749.         if(line.length() > 0)
  750.           backslashEndsPrevLine = (line[line.length() - 1] == '\\');
  751.         else
  752.           backslashEndsPrevLine = false;
  753.  
  754.         // check if this line ends a multi-line #define
  755.         // if so, use the #define's cloned beautifier for the line's indentation
  756.         // and then remove it from the active beautifier stack and delete it.
  757.         if (!backslashEndsPrevLine && isInDefineDefinition && !isInDefine)
  758.           {
  759.             string beautifiedLine;
  760.             ASBeautifier *defineBeautifier;
  761.  
  762.             isInDefineDefinition = false;
  763.             defineBeautifier = activeBeautifierStack->back();
  764.             activeBeautifierStack->pop_back();
  765.  
  766.             beautifiedLine = defineBeautifier->beautify(line);
  767.             delete defineBeautifier;
  768.             return beautifiedLine;
  769.           }
  770.  
  771.         // unless this is a multi-line #define, return this precompiler line as is.
  772.         if (!isInDefine && !isInDefineDefinition)
  773.           return originalLine;
  774.       }
  775.  
  776.     // if there exists any worker beautifier in the activeBeautifierStack,
  777.     // then use it instead of me to indent the current line.
  778.     if (!isInDefine && activeBeautifierStack != NULL && !activeBeautifierStack->empty())
  779.       {
  780.         return activeBeautifierStack->back()->beautify(line);
  781.       }
  782.  
  783.     // calculate preliminary indentation based on data from past lines
  784.     if (!inStatementIndentStack->empty())
  785.       spaceTabCount = inStatementIndentStack->back();
  786.  
  787.  
  788.     for (i=0; i<headerStackSize; i++)
  789.       {
  790.         isInClass = false;
  791.  
  792.         if (blockIndent || (!(i>0 && (*headerStack)[i-1] != &AS_OPEN_BRACKET
  793.                               && (*headerStack)[i] == &AS_OPEN_BRACKET)))
  794.           ++tabCount;
  795.  
  796.         if (isCStyle && !namespaceIndent && i >= 1
  797.             && (*headerStack)[i-1] == &AS_NAMESPACE
  798.             && (*headerStack)[i] == &AS_OPEN_BRACKET)
  799.           --tabCount;
  800.  
  801.         if (isCStyle && i >= 1
  802.             && (*headerStack)[i-1] == &AS_CLASS
  803.             && (*headerStack)[i] == &AS_OPEN_BRACKET )
  804.           {
  805.             if (classIndent)
  806.               ++tabCount;
  807.             isInClass = true;
  808.           }
  809.  
  810.         // is the switchIndent option is on, indent switch statements an additional indent.
  811.         else if (switchIndent && i > 1 &&
  812.                  (*headerStack)[i-1] == &AS_SWITCH &&
  813.                  (*headerStack)[i] == &AS_OPEN_BRACKET
  814.                 )
  815.           {
  816.             ++tabCount;
  817.             isInSwitch = true;
  818.           }
  819.  
  820.       }
  821.  
  822.     if (!lineStartsInComment
  823.         && isCStyle
  824.         && isInClass
  825.         && classIndent
  826.         && headerStackSize >= 2
  827.         &&(*headerStack)[headerStackSize-2] == &AS_CLASS
  828.         && (*headerStack)[headerStackSize-1] == &AS_OPEN_BRACKET
  829.         && line[0] == '}')
  830.       --tabCount;
  831.  
  832.     else if (!lineStartsInComment
  833.              && isInSwitch
  834.              && switchIndent
  835.              && headerStackSize >= 2
  836.              && (*headerStack)[headerStackSize-2] == &AS_SWITCH
  837.              && (*headerStack)[headerStackSize-1] == &AS_OPEN_BRACKET
  838.              && line[0] == '}')
  839.       --tabCount;
  840.  
  841.     if (isInClassHeader)
  842.       {
  843.         isInClassHeaderTab = true;
  844.         tabCount += 2;
  845.       }
  846.  
  847.     if (isInConditional)
  848.       {
  849.         --tabCount;
  850.       }
  851.  
  852.  
  853.     // parse characters in the current line.
  854.  
  855.     for (i=0; i<line.length(); i++)
  856.       {
  857.         tempCh = line[i];
  858.  
  859.         prevCh = ch;
  860.         ch = tempCh;
  861.  
  862.         outBuffer.append(1, ch);
  863.  
  864.         if (isWhiteSpace(ch))
  865.           continue;
  866.  
  867.  
  868.         // handle special characters (i.e. backslash+character such as \n, \t, ...)
  869.         if (isSpecialChar)
  870.           {
  871.             isSpecialChar = false;
  872.             continue;
  873.           }
  874.         if (!(isInComment || isInLineComment) && line.COMPARE(i, 2, string("\\\\")) == 0)
  875.           {
  876.             outBuffer.append(1, '\\');
  877.             i++;
  878.             continue;
  879.           }
  880.         if (!(isInComment || isInLineComment) && ch=='\\')
  881.           {
  882.             isSpecialChar = true;
  883.             continue;
  884.           }
  885.  
  886.         // handle quotes (such as 'x' and "Hello Dolly")
  887.         if (!(isInComment || isInLineComment) && (ch=='"' || ch=='\''))
  888.           if (!isInQuote)
  889.             {
  890.               quoteChar = ch;
  891.               isInQuote = true;
  892.             }
  893.           else if (quoteChar == ch)
  894.             {
  895.               isInQuote = false;
  896.               isInStatement = true;
  897.               continue;
  898.             }
  899.         if (isInQuote)
  900.           continue;
  901.  
  902.         // handle comments
  903.  
  904.         if ( !(isInComment || isInLineComment) && line.COMPARE(i, 2, AS_OPEN_LINE_COMMENT) == 0 )
  905.           {
  906.             isInLineComment = true;
  907.             outBuffer.append(1, '/');
  908.             i++;
  909.             continue;
  910.           }
  911.         else if ( !(isInComment || isInLineComment) && line.COMPARE(i, 2, AS_OPEN_COMMENT) == 0 )
  912.           {
  913.             isInComment = true;
  914.             outBuffer.append(1, '*');
  915.             i++;
  916.             continue;
  917.           }
  918.         else if ( (isInComment || isInLineComment) && line.COMPARE(i, 2, AS_CLOSE_COMMENT) == 0 )
  919.           {
  920.             isInComment = false;
  921.             outBuffer.append(1, '/');
  922.             i++;
  923.             continue;
  924.           }
  925.  
  926.         if (isInComment||isInLineComment)
  927.           continue;
  928.  
  929.         // if we have reached this far then we are NOT in a comment or string of special character...
  930.  
  931.         if (probationHeader != NULL)
  932.           {
  933.             if ( ((probationHeader == &AS_STATIC || probationHeader == &AS_CONST) && ch == '{')
  934.                  || (probationHeader == &AS_SYNCHRONIZED && ch == '('))
  935.               {
  936.                 // insert the probation header as a new header
  937.                 isInHeader = true;
  938.                 headerStack->push_back(probationHeader);
  939.  
  940.                 // handle the specific probation header
  941.                 isInConditional = (probationHeader == &AS_SYNCHRONIZED);
  942.                 if (probationHeader == &AS_CONST)
  943.                   isImmediatelyAfterConst = true;
  944.                 //  isInConst = true;
  945.                 /* TODO:
  946.                  * There is actually no more need for the global isInConst variable.
  947.                                * The only reason for checking const is to see if there is a const
  948.                  * immediately before an open-bracket.
  949.                  * Since CONST is now put into probation and is checked during itspost-char,
  950.                  * isImmediatelyAfterConst can be set by its own...
  951.                  */
  952.  
  953.                 isInStatement = false;
  954.                 // if the probation comes from the previous line, then indent by 1 tab count.
  955.                 if (previousLineProbation && ch == '{')
  956.                   tabCount++;
  957.                 previousLineProbation = false;
  958.               }
  959.  
  960.             // dismiss the probation header
  961.             probationHeader = NULL;
  962.           }
  963.  
  964.         prevNonSpaceCh = currentNonSpaceCh;
  965.         currentNonSpaceCh = ch;
  966.         if (!isLegalNameChar(ch) && ch != ',' && ch != ';' )
  967.           {
  968.             prevNonLegalCh = currentNonLegalCh;
  969.             currentNonLegalCh = ch;
  970.           }
  971.  
  972.         //if (isInConst)
  973.         //{
  974.         //    isInConst = false;
  975.         //    isImmediatelyAfterConst = true;
  976.         //}
  977.  
  978.         if (isInHeader)
  979.           {
  980.             isInHeader = false;
  981.             currentHeader = headerStack->back();
  982.           }
  983.         else
  984.           currentHeader = NULL;
  985.  
  986.         if (isCStyle && isInTemplate
  987.             && (ch == '<' || ch == '>')
  988.             &&  findHeader(line, i, nonAssignmentOperators) == NULL) //;
  989.           {
  990.             if (ch == '<')
  991.               {
  992.                 ++templateDepth;
  993.               }
  994.             else if (ch == '>')
  995.               {
  996.                 if (--templateDepth <= 0)
  997.                   {
  998.                     if (isInTemplate)
  999.                       ch = ';';
  1000.                     else
  1001.                       ch = 't';
  1002.                     isInTemplate = false;
  1003.                     templateDepth = 0;
  1004.                   }
  1005.  
  1006.               }
  1007.           }
  1008.  
  1009.         // handle parenthesies
  1010.         if (ch == '(' || ch == '[' || ch == ')' || ch == ']')
  1011.           {
  1012.             if (ch == '(' || ch == '[')
  1013.               {
  1014.                 if (parenDepth == 0)
  1015.                   {
  1016.                     parenStatementStack->push_back(isInStatement);
  1017.                     isInStatement = true;
  1018.                   }
  1019.                 parenDepth++;
  1020.  
  1021.                 inStatementIndentStackSizeStack->push_back(inStatementIndentStack->size());
  1022.  
  1023.                 if (currentHeader != NULL)
  1024.                   registerInStatementIndent(line, i, spaceTabCount, minConditionalIndent/*indentLength*2*/, true);
  1025.                 else
  1026.                   registerInStatementIndent(line, i, spaceTabCount, 0, true);
  1027.               }
  1028.             else if (ch == ')' || ch == ']')
  1029.               {
  1030.                 parenDepth--;
  1031.                 if (parenDepth == 0)
  1032.                   {
  1033.                     isInStatement = parenStatementStack->back();
  1034.                     parenStatementStack->pop_back();
  1035.                     ch = ' ';
  1036.  
  1037.                     isInConditional = false;
  1038.                   }
  1039.  
  1040.                 if (!inStatementIndentStackSizeStack->empty())
  1041.                   {
  1042.                     unsigned int previousIndentStackSize = inStatementIndentStackSizeStack->back();
  1043.                     inStatementIndentStackSizeStack->pop_back();
  1044.                     while (previousIndentStackSize < inStatementIndentStack->size())
  1045.                       inStatementIndentStack->pop_back();
  1046.  
  1047.                     if (!parenIndentStack->empty())
  1048.                       {
  1049.                         int poppedIndent = parenIndentStack->back();
  1050.                         parenIndentStack->pop_back();
  1051.  
  1052.                         if (i == 0)
  1053.                           spaceTabCount = poppedIndent;
  1054.                       }
  1055.                   }
  1056.               }
  1057.  
  1058.             continue;
  1059.           }
  1060.  
  1061.  
  1062.         if (ch == '{')
  1063.           {
  1064.             bool isBlockOpener = false;
  1065.  
  1066.             // first, check if '{' is a block-opener or an static-array opener
  1067.             isBlockOpener = ( (prevNonSpaceCh == '{' && bracketBlockStateStack->back())
  1068.                               || prevNonSpaceCh == '}'
  1069.                               || prevNonSpaceCh == ')'
  1070.                               || prevNonSpaceCh == ';'
  1071.                               || isInClassHeader
  1072.                               || isBlockOpener
  1073.                               || isImmediatelyAfterConst
  1074.                               || (isInDefine &&
  1075.                                   (prevNonSpaceCh == '('
  1076.                                    || prevNonSpaceCh == '_'
  1077.                                    || isalnum(prevNonSpaceCh))) );
  1078.  
  1079.             isInClassHeader = false;
  1080.             if (!isBlockOpener && currentHeader != NULL)
  1081.               {
  1082.                 for (unsigned int n=0; n < nonParenHeaders.size(); n++)
  1083.                   if (currentHeader == nonParenHeaders[n])
  1084.                     {
  1085.                       isBlockOpener = true;
  1086.                       break;
  1087.                     }
  1088.               }
  1089.             bracketBlockStateStack->push_back(isBlockOpener);
  1090.             if (!isBlockOpener)
  1091.               {
  1092.                 inStatementIndentStackSizeStack->push_back(inStatementIndentStack->size());
  1093.                 registerInStatementIndent(line, i, spaceTabCount, 0, true);
  1094.                 parenDepth++;
  1095.                 if (i == 0)
  1096.                   shouldIndentBrackettedLine = false;
  1097.  
  1098.                 continue;
  1099.               }
  1100.  
  1101.             // this bracket is a block opener...
  1102.  
  1103.             ++lineOpeningBlocksNum;
  1104.  
  1105.             if (isInClassHeader)
  1106.               isInClassHeader = false;
  1107.             if (isInClassHeaderTab)
  1108.               {
  1109.                 isInClassHeaderTab = false;
  1110.                 tabCount -= 2;
  1111.               }
  1112.  
  1113.             blockParenDepthStack->push_back(parenDepth);
  1114.             blockStatementStack->push_back(isInStatement);
  1115.  
  1116.             inStatementIndentStackSizeStack->push_back(inStatementIndentStack->size());
  1117.  
  1118.             blockTabCount += isInStatement? 1 : 0;
  1119.             parenDepth = 0;
  1120.             isInStatement = false;
  1121.  
  1122.             tempStacks->push_back(new vector<const string*>);
  1123.             headerStack->push_back(&AS_OPEN_BRACKET);
  1124.             lastLineHeader = &AS_OPEN_BRACKET; // <------
  1125.  
  1126.             continue;
  1127.           }
  1128.  
  1129.         //check if a header has been reached
  1130.         if (prevCh == ' ')
  1131.           {
  1132.             bool isIndentableHeader = true;
  1133.             const string *newHeader = findHeader(line, i, headers);
  1134.             if (newHeader != NULL)
  1135.               {
  1136.                 // if we reached here, then this is a header...
  1137.                 isInHeader = true;
  1138.  
  1139.                 vector<const string*> *lastTempStack;
  1140.                 if (tempStacks->empty())
  1141.                   lastTempStack = NULL;
  1142.                 else
  1143.                   lastTempStack = tempStacks->back();
  1144.  
  1145.                 // if a new block is opened, push a new stack into tempStacks to hold the
  1146.                 // future list of headers in the new block.
  1147.  
  1148.                 // take care of the special case: 'else if (...)'
  1149.                 if (newHeader == &AS_IF && lastLineHeader == &AS_ELSE)
  1150.                   {
  1151.                     //spaceTabCount += indentLength; // to counter the opposite addition that occurs when the 'if' is registered below...
  1152.                     headerStack->pop_back();
  1153.                   }
  1154.  
  1155.                 // take care of 'else'
  1156.                 else if (newHeader == &AS_ELSE)
  1157.                   {
  1158.                     if (lastTempStack != NULL)
  1159.                       {
  1160.                         int indexOfIf = indexOf(*lastTempStack, &AS_IF); // <---
  1161.                         if (indexOfIf != -1)
  1162.                           {
  1163.                             // recreate the header list in headerStack up to the previous 'if'
  1164.                             // from the temporary snapshot stored in lastTempStack.
  1165.                             int restackSize = lastTempStack->size() - indexOfIf - 1;
  1166.                             for (int r=0; r<restackSize; r++)
  1167.                               {
  1168.                                 headerStack->push_back(lastTempStack->back());
  1169.                                 lastTempStack->pop_back();
  1170.                               }
  1171.                             if (!closingBracketReached)
  1172.                               tabCount += restackSize;
  1173.                           }
  1174.                         /*
  1175.                          * If the above if is not true, i.e. no 'if' before the 'else',
  1176.                          * then nothing beautiful will come out of this...
  1177.                          * I should think about inserting an Exception here to notify the caller of this...
  1178.                          */
  1179.                       }
  1180.                   }
  1181.  
  1182.                 // check if 'while' closes a previous 'do'
  1183.                 else if (newHeader == &AS_WHILE)
  1184.                   {
  1185.                     if (lastTempStack != NULL)
  1186.                       {
  1187.                         int indexOfDo = indexOf(*lastTempStack, &AS_DO); // <---
  1188.                         if (indexOfDo != -1)
  1189.                           {
  1190.                             // recreate the header list in headerStack up to the previous 'do'
  1191.                             // from the temporary snapshot stored in lastTempStack.
  1192.                             int restackSize = lastTempStack->size() - indexOfDo - 1;
  1193.                             for (int r=0; r<restackSize; r++)
  1194.                               {
  1195.                                 headerStack->push_back(lastTempStack->back());
  1196.                                 lastTempStack->pop_back();
  1197.                               }
  1198.                             if (!closingBracketReached)
  1199.                               tabCount += restackSize;
  1200.                           }
  1201.                       }
  1202.                   }
  1203.                 // check if 'catch' closes a previous 'try' or 'catch'
  1204.                 else if (newHeader == &AS_CATCH || newHeader == &AS_FINALLY)
  1205.                   {
  1206.                     if (lastTempStack != NULL)
  1207.                       {
  1208.                         int indexOfTry = indexOf(*lastTempStack, &AS_TRY);
  1209.                         if (indexOfTry == -1)
  1210.                           indexOfTry = indexOf(*lastTempStack, &AS_CATCH);
  1211.                         if (indexOfTry != -1)
  1212.                           {
  1213.                             // recreate the header list in headerStack up to the previous 'try'
  1214.                             // from the temporary snapshot stored in lastTempStack.
  1215.                             int restackSize = lastTempStack->size() - indexOfTry - 1;
  1216.                             for (int r=0; r<restackSize; r++)
  1217.                               {
  1218.                                 headerStack->push_back(lastTempStack->back());
  1219.                                 lastTempStack->pop_back();
  1220.                               }
  1221.  
  1222.                             if (!closingBracketReached)
  1223.                               tabCount += restackSize;
  1224.                           }
  1225.                       }
  1226.                   }
  1227.                 else if (newHeader == &AS_CASE)
  1228.                   {
  1229.                     isInCase = true;
  1230.                     if (!caseIndent)
  1231.                       --tabCount;
  1232.                   }
  1233.                 else if(newHeader == &AS_DEFAULT)
  1234.                   {
  1235.                     isInCase = true;
  1236.                     if (!caseIndent)
  1237.                       --tabCount;
  1238.                   }
  1239.                 else if (newHeader == &AS_PUBLIC || newHeader == &AS_PROTECTED || newHeader == &AS_PRIVATE)
  1240.                   {
  1241.                     if (isCStyle && !isInClassHeader)
  1242.                       --tabCount;
  1243.                     isIndentableHeader = false;
  1244.                   }
  1245.                 //else if ((newHeader == &STATIC || newHeader == &SYNCHRONIZED) &&
  1246.                 //         !headerStack->empty() &&
  1247.                 //         (headerStack->back() == &STATIC || headerStack->back() == &SYNCHRONIZED))
  1248.                 //{
  1249.                 //    isIndentableHeader = false;
  1250.                 //}
  1251.                 else if (newHeader == &AS_STATIC
  1252.                          || newHeader == &AS_SYNCHRONIZED
  1253.                          || (newHeader == &AS_CONST && isCStyle))
  1254.                   {
  1255.                     if (!headerStack->empty() &&
  1256.                         (headerStack->back() == &AS_STATIC
  1257.                          || headerStack->back() == &AS_SYNCHRONIZED
  1258.                          || headerStack->back() == &AS_CONST))
  1259.                       {
  1260.                         isIndentableHeader = false;
  1261.                       }
  1262.                     else
  1263.                       {
  1264.                         isIndentableHeader = false;
  1265.                         probationHeader = newHeader;
  1266.                       }
  1267.                   }
  1268.                 else if (newHeader == &AS_CONST)
  1269.                   {
  1270.                     // this will be entered only if NOT in C style
  1271.                     // since otherwise the CONST would be found to be a probstion header...
  1272.  
  1273.                     //if (isCStyle)
  1274.                     //  isInConst = true;
  1275.                     isIndentableHeader = false;
  1276.                   }
  1277.                 /*
  1278.                               else if (newHeader == &OPERATOR)
  1279.                               {
  1280.                                   if (isCStyle)
  1281.                                       isInOperator = true;
  1282.                                   isIndentableHeader = false;
  1283.                               }
  1284.                 */
  1285.                 else if (newHeader == &AS_TEMPLATE)
  1286.                   {
  1287.                     if (isCStyle)
  1288.                       isInTemplate = true;
  1289.                     isIndentableHeader = false;
  1290.                   }
  1291.  
  1292.  
  1293.                 if (isIndentableHeader)
  1294.                   {
  1295.                     // 3.2.99
  1296.                     //spaceTabCount-=indentLength;
  1297.                     headerStack->push_back(newHeader);
  1298.                     isInStatement = false;
  1299.                     if (indexOf(nonParenHeaders, newHeader) == -1)
  1300.                       {
  1301.                         isInConditional = true;
  1302.                       }
  1303.                     lastLineHeader = newHeader;
  1304.                   }
  1305.                 else
  1306.                   isInHeader = false;
  1307.  
  1308.                 //lastLineHeader = newHeader;
  1309.  
  1310.                 outBuffer.append(newHeader->substr(1));
  1311.                 i += newHeader->length() - 1;
  1312.  
  1313.                 continue;
  1314.               }
  1315.           }
  1316.  
  1317.         if (isCStyle && !isalpha(prevCh)
  1318.             && line.COMPARE(i, 8, AS_OPERATOR) == 0 && !isalnum(line[i+8]))
  1319.           {
  1320.             isInOperator = true;
  1321.             outBuffer.append(AS_OPERATOR.substr(1));
  1322.             i += 7;
  1323.             continue;
  1324.           }
  1325.  
  1326.         if (ch == '?')
  1327.           isInQuestion = true;
  1328.  
  1329.  
  1330.         // special handling of 'case' statements
  1331.         if (ch == ':')
  1332.           {
  1333.             if (line.length() > i+1 && line[i+1] == ':') // look for ::
  1334.               {
  1335.                 ++i;
  1336.                 outBuffer.append(1, ':');
  1337.                 ch = ' ';
  1338.                 continue;
  1339.               }
  1340.  
  1341.             else if (isCStyle && isInClass && prevNonSpaceCh != ')')
  1342.               {
  1343.               // BEGIN Content of ASBeautifier.cpp.BITFIELD.patch:
  1344.               
  1345.                 unsigned int chIndex;
  1346.                    char nextCh = 0;
  1347.                 for (chIndex = i+1; chIndex < line.length(); chIndex++)
  1348.                     if (!isWhiteSpace(line[chIndex]))
  1349.                         break;
  1350.                     if (chIndex< line.length())
  1351.                            nextCh = line[chIndex];
  1352.                 int nWord =0;
  1353.                 for (chIndex = 0; chIndex < i; chIndex++)
  1354.                 {
  1355.                     if (!isWhiteSpace(line[chIndex]))
  1356.                     {
  1357.                         nWord ++;
  1358.                         while (!isWhiteSpace(line[++chIndex]));
  1359.                     }                                    
  1360.                 }
  1361.                 if ((nextCh >= '0' && nextCh <= '9') || (nWord >1))
  1362.                     continue;
  1363.               // END Content of ASBeautifier.cpp.BITFIELD.patch:
  1364.                 
  1365.                 --tabCount;
  1366.                 // found a 'private:' or 'public:' inside a class definition
  1367.                 // so do nothing special
  1368.               }
  1369.  
  1370.             else if (isCStyle && isInClassHeader)
  1371.               {
  1372.  
  1373.                 // found a 'class A : public B' definition
  1374.                 // so do nothing special
  1375.               }
  1376.  
  1377.             else if (isInQuestion)
  1378.               {
  1379.                 isInQuestion = false;
  1380.               }
  1381.             else if (isCStyle && prevNonSpaceCh == ')')
  1382.               {
  1383.                 isInClassHeader = true;
  1384.                 if (i==0)
  1385.                   tabCount += 2;
  1386.               }
  1387.             else
  1388.               {
  1389.                 currentNonSpaceCh = ';'; // so that brackets after the ':' will appear as block-openers
  1390.                 if (isInCase)
  1391.                   {
  1392.                     isInCase = false;
  1393.                     ch = ';'; // from here on, treat char as ';'
  1394.                   } 
  1395.               // BEGIN content of ASBeautifier.cpp.BITFIELD.patch.bz2
  1396.               else // bitfield or labels
  1397.                                 {
  1398.                 unsigned int chIndex;
  1399.                 char nextCh = 0;
  1400.                 for (chIndex = i+1; (isCStyle && chIndex < line.length()); chIndex++)
  1401.                     if (!isWhiteSpace(line[chIndex]))
  1402.                         break;
  1403.                 if (chIndex< line.length())
  1404.                     nextCh = line[chIndex];
  1405.  
  1406.                  int nWord =0;
  1407.                  for (chIndex = 0; chIndex < i; chIndex++)
  1408.                 {
  1409.                     if (!isWhiteSpace(line[chIndex]))
  1410.                     {
  1411.                         nWord ++;
  1412.                         while (!isWhiteSpace(line[++chIndex]));
  1413.                     }                                    
  1414.                 }
  1415.                  if (isCStyle &&  (nextCh >= '0' && nextCh <= '9') || (nWord >1))
  1416.                 {
  1417.                     continue;
  1418.                 }
  1419.                 // END content of ASASBeautifier.cpp.BITFIELD.patch.bz2
  1420.  
  1421.                 else // is in a label (e.g. 'label1:')
  1422.                   {
  1423.                     if (labelIndent)
  1424.                       --tabCount; // unindent label by one indent
  1425.                     else
  1426.                       tabCount = 0; // completely flush indent to left
  1427.                   }
  1428.  
  1429.               // BEGIN content of ASASBeautifier.cpp.BITFIELD.patch.bz2
  1430.                 }
  1431.             // END content of ASASBeautifier.cpp.BITFIELD.patch.bz2
  1432.  
  1433.               }
  1434.           }
  1435.  
  1436.         if ((ch == ';'  || (parenDepth>0 && ch == ','))  && !inStatementIndentStackSizeStack->empty())
  1437.           while ((unsigned int)inStatementIndentStackSizeStack->back() + (parenDepth>0 ? 1 : 0)  < inStatementIndentStack->size())
  1438.             inStatementIndentStack->pop_back();
  1439.  
  1440.  
  1441.         // handle ends of statements
  1442.         if ( (ch == ';' && parenDepth == 0) || ch == '}'/* || (ch == ',' && parenDepth == 0)*/)
  1443.           {
  1444.             if (ch == '}')
  1445.               {
  1446.                 // first check if this '}' closes a previous block, or a static array...
  1447.                 if (!bracketBlockStateStack->empty())
  1448.                   {
  1449.                     bool bracketBlockState = bracketBlockStateStack->back();
  1450.                     bracketBlockStateStack->pop_back();
  1451.                     if (!bracketBlockState)
  1452.                       {
  1453.                         if (!inStatementIndentStackSizeStack->empty())
  1454.                           {
  1455.                             // this bracket is a static array
  1456.  
  1457.                             unsigned int previousIndentStackSize = inStatementIndentStackSizeStack->back();
  1458.                             inStatementIndentStackSizeStack->pop_back();
  1459.                             while (previousIndentStackSize < inStatementIndentStack->size())
  1460.                               inStatementIndentStack->pop_back();
  1461.                             parenDepth--;
  1462.                             if (i == 0)
  1463.                               shouldIndentBrackettedLine = false;
  1464.  
  1465.                             if (!parenIndentStack->empty())
  1466.                               {
  1467.                                 int poppedIndent = parenIndentStack->back();
  1468.                                 parenIndentStack->pop_back();
  1469.                                 if (i == 0)
  1470.                                   spaceTabCount = poppedIndent;
  1471.                               }
  1472.                           }
  1473.                         continue;
  1474.                       }
  1475.                   }
  1476.  
  1477.                 // this bracket is block closer...
  1478.  
  1479.                 ++lineClosingBlocksNum;
  1480.  
  1481.                 if(!inStatementIndentStackSizeStack->empty())
  1482.                   inStatementIndentStackSizeStack->pop_back();
  1483.  
  1484.                 if (!blockParenDepthStack->empty())
  1485.                   {
  1486.                     parenDepth = blockParenDepthStack->back();
  1487.                     blockParenDepthStack->pop_back();
  1488.                     isInStatement = blockStatementStack->back();
  1489.                     blockStatementStack->pop_back();
  1490.  
  1491.                     if (isInStatement)
  1492.                       blockTabCount--;
  1493.                   }
  1494.  
  1495.                 closingBracketReached = true;
  1496.                 int headerPlace = indexOf(*headerStack, &AS_OPEN_BRACKET); // <---
  1497.                 if (headerPlace != -1)
  1498.                   {
  1499.                     const string *popped = headerStack->back();
  1500.                     while (popped != &AS_OPEN_BRACKET)
  1501.                       {
  1502.                         headerStack->pop_back();
  1503.                         popped = headerStack->back();
  1504.                       }
  1505.                     headerStack->pop_back();
  1506.  
  1507.                     if (!tempStacks->empty())
  1508.                       {
  1509.                         vector<const string*> *temp =  tempStacks->back();
  1510.                         tempStacks->pop_back();
  1511.                         delete temp;
  1512.                       }
  1513.                   }
  1514.  
  1515.  
  1516.                 ch = ' '; // needed due to cases such as '}else{', so that headers ('else' tn tih case) will be identified...
  1517.               }
  1518.  
  1519.             /*
  1520.              * Create a temporary snapshot of the current block's header-list in the
  1521.              * uppermost inner stack in tempStacks, and clear the headerStack up to
  1522.              * the begining of the block.
  1523.              * Thus, the next future statement will think it comes one indent past
  1524.              * the block's '{' unless it specifically checks for a companion-header
  1525.              * (such as a previous 'if' for an 'else' header) within the tempStacks,
  1526.              * and recreates the temporary snapshot by manipulating the tempStacks.
  1527.              */
  1528.             if (!tempStacks->back()->empty())
  1529.               while (!tempStacks->back()->empty())
  1530.                 tempStacks->back()->pop_back();
  1531.             while (!headerStack->empty() && headerStack->back() != &AS_OPEN_BRACKET)
  1532.               {
  1533.                 tempStacks->back()->push_back(headerStack->back());
  1534.                 headerStack->pop_back();
  1535.               }
  1536.  
  1537.             if (parenDepth == 0 && ch == ';')
  1538.               isInStatement=false;
  1539.  
  1540.             isInClassHeader = false;
  1541.  
  1542.             continue;
  1543.           }
  1544.  
  1545.  
  1546.         // check for preBlockStatements ONLY if not within parenthesies
  1547.         // (otherwise 'struct XXX' statements would be wrongly interpreted...)
  1548.         if (prevCh == ' ' && !isInTemplate && parenDepth == 0)
  1549.           {
  1550.             const string *newHeader = findHeader(line, i, preBlockStatements);
  1551.             if (newHeader != NULL)
  1552.               {
  1553.                 isInClassHeader = true;
  1554.                 outBuffer.append(newHeader->substr(1));
  1555.                 i += newHeader->length() - 1;
  1556.                 //if (isCStyle)
  1557.                 headerStack->push_back(newHeader);
  1558.               }
  1559.           }
  1560.  
  1561.         // Handle operators
  1562.         //
  1563.  
  1564.         ////        // PRECHECK if a '==' or '--' or '++' operator was reached.
  1565.         ////        // If not, then register an indent IF an assignment operator was reached.
  1566.         ////        // The precheck is important, so that statements such as 'i--==2' are not recognized
  1567.         ////        // to have assignment operators (here, '-=') in them . . .
  1568.  
  1569.         const string *foundAssignmentOp = NULL;
  1570.         const string *foundNonAssignmentOp = NULL;
  1571.  
  1572.         immediatelyPreviousAssignmentOp = NULL;
  1573.  
  1574.         // Check if an operator has been reached.
  1575.         foundAssignmentOp = findHeader(line, i, assignmentOperators, false);
  1576.         foundNonAssignmentOp = findHeader(line, i, nonAssignmentOperators, false);
  1577.  
  1578.         // Since findHeader's boundry checking was not used above, it is possible
  1579.         // that both an assignment op and a non-assignment op where found,
  1580.         // e.g. '>>' and '>>='. If this is the case, treat the LONGER one as the
  1581.         // found operator.
  1582.         if (foundAssignmentOp != NULL && foundNonAssignmentOp != NULL)
  1583.           if (foundAssignmentOp->length() < foundNonAssignmentOp->length())
  1584.             foundAssignmentOp = NULL;
  1585.           else
  1586.             foundNonAssignmentOp = NULL;
  1587.  
  1588.         if (foundNonAssignmentOp != NULL)
  1589.           {
  1590.             if (foundNonAssignmentOp->length() > 1)
  1591.               {
  1592.                 outBuffer.append(foundNonAssignmentOp->substr(1));
  1593.                 i += foundNonAssignmentOp->length() - 1;
  1594.               }
  1595.           }
  1596.  
  1597.         else if (foundAssignmentOp != NULL)
  1598.  
  1599.           {
  1600.             if (foundAssignmentOp->length() > 1)
  1601.               {
  1602.                 outBuffer.append(foundAssignmentOp->substr(1));
  1603.                 i += foundAssignmentOp->length() - 1;
  1604.               }
  1605.  
  1606.             if (!isInOperator && !isInTemplate)
  1607.               {
  1608.                 registerInStatementIndent(line, i, spaceTabCount, 0, false);
  1609.                 immediatelyPreviousAssignmentOp = foundAssignmentOp;
  1610.                 isInStatement = true;
  1611.               }
  1612.           }
  1613.  
  1614.         /*
  1615.                 immediatelyPreviousAssignmentOp = NULL;
  1616.                 bool isNonAssingmentOperator = false;
  1617.                 for (int n = 0; n < nonAssignmentOperators.size(); n++)
  1618.                     if (line.COMPARE(i, nonAssignmentOperators[n]->length(), *(nonAssignmentOperators[n])) == 0)
  1619.                     {
  1620.                         if (nonAssignmentOperators[n]->length() > 1)
  1621.                         {
  1622.                             outBuffer.append(nonAssignmentOperators[n]->substr(1));
  1623.                             i += nonAssignmentOperators[n]->length() - 1;
  1624.                         }
  1625.                         isNonAssingmentOperator = true;
  1626.                         break;
  1627.                     }
  1628.                 if (!isNonAssingmentOperator)
  1629.                 {
  1630.                     for (int a = 0; a < assignmentOperators.size(); a++)
  1631.                         if (line.COMPARE(i, assignmentOperators[a]->length(), *(assignmentOperators[a])) == 0)
  1632.                         {
  1633.                             if (assignmentOperators[a]->length() > 1)
  1634.                             {
  1635.                                 outBuffer.append(assignmentOperators[a]->substr(1));
  1636.                                 i += assignmentOperators[a]->length() - 1;
  1637.                             }
  1638.          
  1639.                             if (!isInOperator && !isInTemplate)
  1640.                             {
  1641.                                 registerInStatementIndent(line, i, spaceTabCount, 0, false);
  1642.                                 immediatelyPreviousAssignmentOp = assignmentOperators[a];
  1643.                                 isInStatement = true;
  1644.                             }
  1645.                             break;
  1646.                         }
  1647.                 }
  1648.         */
  1649.  
  1650.         if (isInOperator)
  1651.           isInOperator = false;
  1652.       }
  1653.  
  1654.     // handle special cases of unindentation:
  1655.  
  1656.     /*
  1657.      * if '{' doesn't follow an immediately previous '{' in the headerStack
  1658.      * (but rather another header such as "for" or "if", then unindent it
  1659.      * by one indentation relative to its block.
  1660.      */
  1661.     //    cerr << endl << lineOpeningBlocksNum << " " <<  lineClosingBlocksNum << " " <<  previousLastLineHeader << endl;
  1662.  
  1663.     // indent #define lines with one less tab
  1664.     //if (isInDefine)
  1665.     //    tabCount -= defineTabCount-1;
  1666.  
  1667.  
  1668.     if (!lineStartsInComment
  1669.         && !blockIndent
  1670.         && outBuffer.length()>0
  1671.         && outBuffer[0]=='{'
  1672.         && !(lineOpeningBlocksNum > 0 && lineOpeningBlocksNum == lineClosingBlocksNum)
  1673.         && !(headerStack->size() > 1 && (*headerStack)[headerStack->size()-2] == &AS_OPEN_BRACKET)
  1674.         && shouldIndentBrackettedLine)
  1675.       --tabCount;
  1676.  
  1677.     else if (!lineStartsInComment
  1678.              && outBuffer.length()>0
  1679.              && outBuffer[0]=='}'
  1680.              && shouldIndentBrackettedLine )
  1681.       --tabCount;
  1682.  
  1683.     // correctly indent one-line-blocks...
  1684.     else if (!lineStartsInComment
  1685.              && outBuffer.length()>0
  1686.              && lineOpeningBlocksNum > 0
  1687.              && lineOpeningBlocksNum == lineClosingBlocksNum
  1688.              && previousLastLineHeader != NULL
  1689.              && previousLastLineHeader != &AS_OPEN_BRACKET)
  1690.       tabCount -= 1; //lineOpeningBlocksNum - (blockIndent ? 1 : 0);
  1691.  
  1692.     if (tabCount < 0)
  1693.       tabCount = 0;
  1694.  
  1695.     // take care of extra bracket indentatation option...
  1696.     if (bracketIndent && outBuffer.length()>0 && shouldIndentBrackettedLine)
  1697.       if (outBuffer[0]=='{' || outBuffer[0]=='}')
  1698.         tabCount++;
  1699.  
  1700.  
  1701.     if (isInDefine)
  1702.       {
  1703.         if (outBuffer[0] == '#')
  1704.           {
  1705.             string preproc = trim(string(outBuffer.c_str() + 1));
  1706.             if (preproc.COMPARE(0, 6, string("define")) == 0)
  1707.               {
  1708.                 if (!inStatementIndentStack->empty()
  1709.                     && inStatementIndentStack->back() > 0)
  1710.                   {
  1711.                     defineTabCount = tabCount;
  1712.                   }
  1713.                 else
  1714.                   {
  1715.                     defineTabCount = tabCount - 1;
  1716.                     tabCount--;
  1717.                   }
  1718.               }
  1719.           }
  1720.  
  1721.         tabCount -= defineTabCount;
  1722.       }
  1723.  
  1724.     if (tabCount < 0)
  1725.       tabCount = 0;
  1726.  
  1727.  
  1728.     // finally, insert indentations into begining of line
  1729.  
  1730.     prevFinalLineSpaceTabCount = spaceTabCount;
  1731.     prevFinalLineTabCount = tabCount;
  1732.  
  1733.     if (shouldForceTabIndentation)
  1734.       {
  1735.         tabCount += spaceTabCount / indentLength;
  1736.         spaceTabCount = spaceTabCount % indentLength;
  1737.       }
  1738.  
  1739.     outBuffer = preLineWS(spaceTabCount,tabCount) + outBuffer;
  1740.  
  1741.     if (lastLineHeader != NULL)
  1742.       previousLastLineHeader = lastLineHeader;
  1743.  
  1744.     return outBuffer;
  1745.   }
  1746.  
  1747.  
  1748.   string ASBeautifier::preLineWS(int spaceTabCount, int tabCount)
  1749.   {
  1750.     string ws;
  1751.  
  1752.     for (int i=0; i<tabCount; i++)
  1753.       ws += indentString;
  1754.  
  1755.     while ((spaceTabCount--) > 0)
  1756.       ws += string(" ");
  1757.  
  1758.     return ws;
  1759.  
  1760.   }
  1761.  
  1762.   /**
  1763.    * register an in-statement indent.
  1764.    */
  1765.   void ASBeautifier::registerInStatementIndent(const string &line, int i, int spaceTabCount,
  1766.       int minIndent, bool updateParenStack)
  1767.   {
  1768.     int inStatementIndent;
  1769.     int remainingCharNum = line.length() - i;
  1770.     int nextNonWSChar = 1;
  1771.  
  1772.     nextNonWSChar = getNextProgramCharDistance(line, i);
  1773.  
  1774.     // if indent is around the last char in the line, indent instead 2 spaces from the previous indent
  1775.     if (nextNonWSChar == remainingCharNum)
  1776.       {
  1777.         int previousIndent = spaceTabCount;
  1778.         if (!inStatementIndentStack->empty())
  1779.           previousIndent = inStatementIndentStack->back();
  1780.  
  1781.         inStatementIndentStack->push_back(/*2*/ indentLength + previousIndent );
  1782.         if (updateParenStack)
  1783.           parenIndentStack->push_back( previousIndent );
  1784.         return;
  1785.       }
  1786.  
  1787.     if (updateParenStack)
  1788.       parenIndentStack->push_back(i+spaceTabCount);
  1789.  
  1790.     inStatementIndent = i + nextNonWSChar + spaceTabCount;
  1791.  
  1792.     if (i + nextNonWSChar < minIndent)
  1793.       inStatementIndent = minIndent + spaceTabCount;
  1794.  
  1795.     if (i + nextNonWSChar > maxInStatementIndent)
  1796.       inStatementIndent =  indentLength*2 + spaceTabCount;
  1797.  
  1798.  
  1799.  
  1800.     if (!inStatementIndentStack->empty() &&
  1801.         inStatementIndent < inStatementIndentStack->back())
  1802.       inStatementIndent = inStatementIndentStack->back();
  1803.  
  1804.     inStatementIndentStack->push_back(inStatementIndent);
  1805.   }
  1806.  
  1807.   /**
  1808.    * get distance to the next non-white sspace, non-comment character in the line.
  1809.    * if no such character exists, return the length remaining to the end of the line.
  1810.    */
  1811.   int ASBeautifier::getNextProgramCharDistance(const string &line, int i)
  1812.   {
  1813.     bool inComment = false;
  1814.     int remainingCharNum = line.length() - i;
  1815.     int charDistance = 1;
  1816.     int ch;
  1817.  
  1818.     for (charDistance = 1; charDistance < remainingCharNum; charDistance++)
  1819.       {
  1820.         ch = line[i + charDistance];
  1821.         if (inComment)
  1822.           {
  1823.             if (line.COMPARE(i + charDistance, 2, AS_CLOSE_COMMENT) == 0)
  1824.               {
  1825.                 charDistance++;
  1826.                 inComment = false;
  1827.               }
  1828.             continue;
  1829.           }
  1830.         else if (isWhiteSpace(ch))
  1831.           continue;
  1832.         else if (ch == '/')
  1833.           {
  1834.             if (line.COMPARE(i + charDistance, 2, AS_OPEN_LINE_COMMENT) == 0)
  1835.               return remainingCharNum;
  1836.             else if (line.COMPARE(i + charDistance, 2, AS_OPEN_COMMENT) == 0)
  1837.               {
  1838.                 charDistance++;
  1839.                 inComment = true;
  1840.               }
  1841.           }
  1842.         else
  1843.           return charDistance;
  1844.       }
  1845.  
  1846.     return charDistance;
  1847.   }
  1848.  
  1849.  
  1850.   /**
  1851.    * check if a specific character can be used in a legal variable/method/class name
  1852.    *
  1853.    * @return          legality of the char.
  1854.    * @param ch        the character to be checked.
  1855.    */
  1856.   bool ASBeautifier::isLegalNameChar(char ch) const
  1857.     {
  1858.       return (isalnum(ch) //(ch>='a' && ch<='z') || (ch>='A' && ch<='Z') || (ch>='0' && ch<='9') ||
  1859.               || ch=='.' || ch=='_' || (!isCStyle && ch=='$') || (isCStyle && ch=='~'));
  1860.     }
  1861.  
  1862.  
  1863.   /**
  1864.    * check if a specific line position contains a header, out of several possible headers.
  1865.    *
  1866.    * @return    a pointer to the found header. if no header was found then return NULL.
  1867.    */
  1868.   const string *ASBeautifier::findHeader(const string &line, int i, const vector<const string*> &possibleHeaders, bool checkBoundry)
  1869.   {
  1870.     int maxHeaders = possibleHeaders.size();
  1871.     const string *header = NULL;
  1872.     int p;
  1873.  
  1874.     for (p=0; p < maxHeaders; p++)
  1875.       {
  1876.         header = possibleHeaders[p];
  1877.  
  1878.         if (line.COMPARE(i, header->length(), *header) == 0)
  1879.           {
  1880.             // check that this is a header and not a part of a longer word
  1881.             // (e.g. not at its begining, not at its middle...)
  1882.  
  1883.             int lineLength = line.length();
  1884.             int headerEnd = i + header->length();
  1885.             char startCh = (*header)[0];   // first char of header
  1886.             char endCh = 0;                // char just after header
  1887.             char prevCh = 0;               // char just before header
  1888.  
  1889.             if (headerEnd < lineLength)
  1890.               {
  1891.                 endCh = line[headerEnd];
  1892.               }
  1893.             if (i > 0)
  1894.               {
  1895.                 prevCh = line[i-1];
  1896.               }
  1897.  
  1898.             if (!checkBoundry)
  1899.               {
  1900.                 return header;
  1901.               }
  1902.             else if (prevCh != 0
  1903.                      && isLegalNameChar(startCh)
  1904.                      && isLegalNameChar(prevCh))
  1905.               {
  1906.                 return NULL;
  1907.               }
  1908.             else if (headerEnd >= lineLength
  1909.                      || !isLegalNameChar(startCh)
  1910.                      || !isLegalNameChar(endCh))
  1911.               {
  1912.                 return header;
  1913.               }
  1914.             else
  1915.               {
  1916.                 return NULL;
  1917.               }
  1918.           }
  1919.       }
  1920.  
  1921.     return NULL;
  1922.   }
  1923.  
  1924.  
  1925.   /**
  1926.    * check if a specific character can be used in a legal variable/method/class name
  1927.    *
  1928.    * @return          legality of the char.
  1929.    * @param ch        the character to be checked.
  1930.    */
  1931.   bool ASBeautifier::isWhiteSpace(char ch) const
  1932.     {
  1933.       return (ch == ' ' || ch == '\t');
  1934.     }
  1935.  
  1936.   /**
  1937.    * find the index number of a string element in a container of strings
  1938.    *
  1939.    * @return              the index number of element in the ocntainer. -1 if element not found.
  1940.    * @param container     a vector of strings.
  1941.    * @param element       the element to find .
  1942.    */
  1943.   int ASBeautifier::indexOf(vector<const string*> &container, const string *element)
  1944.   {
  1945.     vector<const string*>::const_iterator where;
  1946.  
  1947.     where= find(container.begin(), container.end(), element);
  1948.     if (where == container.end())
  1949.       return -1;
  1950.     else
  1951.       return where - container.begin();
  1952.   }
  1953.  
  1954.   /**
  1955.    * trim removes the white space surrounding a line.
  1956.    *
  1957.    * @return          the trimmed line.
  1958.    * @param str       the line to trim.
  1959.    */
  1960.   string ASBeautifier::trim(const string &str)
  1961.   {
  1962.  
  1963.     int start = 0;
  1964.     int end = str.length() - 1;
  1965.  
  1966.     while (start < end && isWhiteSpace(str[start]))
  1967.       start++;
  1968.  
  1969.     while (start <= end && isWhiteSpace(str[end]))
  1970.       end--;
  1971.  
  1972.     string returnStr(str, start, end+1-start);
  1973.     return returnStr;
  1974.   }
  1975.  
  1976. #ifdef USES_NAMESPACE
  1977. }
  1978. #endif
  1979.